package com.hemerasolutions.v2trainer.model.exerciseGroup;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;

import com.hemerasolutions.v2trainer.model.base.BaseModel;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.interfaces.BaseReferencedModelInterface;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.training.Training;
import com.hemerasolutions.v2trainer.model.training.TrainingType;
import com.hemerasolutions.v2trainer.model.users.User;
import com.hemerasolutions.v2trainer.util.Utility;
import com.hemerasolutions.v2trainer.util.annotations.ReferencedModel;

@Entity
public class ExerciseGroup extends BaseModel implements BaseReferencedModelInterface {
 
	private static final long serialVersionUID = 1L;
	
	private static String nameKey = "ExerciseGroup";	
	
    @Column(length = 50)
	private String name;

    @Column(length = 180)
	private String description;
	 
    @Column(length=180)
	private String obs;
    
    @Column(length=2)
    private int version;

    @Temporal(javax.persistence.TemporalType.TIMESTAMP)		
	private Date createdAt;

    @Temporal(javax.persistence.TemporalType.TIMESTAMP)	
	private Date lastChange;
	 
	@OneToOne 
	private User changedBy;

    @Column
	private boolean active;	
	
    @ManyToOne
	private TrainingType trainingType;
	
    @ManyToOne
    @ReferencedModel(compareOnChange = true)
    private Modality modality;

    @ManyToOne
    private VersionableExerciseGroup versionableExerciseGroup;

    @ManyToMany
    @ReferencedModel(compareOnChange = true)
    private List<Exercise> exercises;

    @ManyToMany
    @ReferencedModel(compareOnChange = true)
    private List<Training> usedTrainings;

	public ExerciseGroup() {
		super();
		
		this.usedTrainings = new ArrayList<Training>();
		this.lastChange = Utility.getRoundedDate();
		this.createdAt = Utility.getRoundedDate();
		this.exercises = new ArrayList<Exercise>();
	}

    
    public ExerciseGroup(ExerciseGroup other, VersionableExerciseGroup versionableExerciseGroup ){
    	this();
    	
    	
    	this.versionableExerciseGroup = versionableExerciseGroup;
    	this.trainingType = other.trainingType;
    	this.name = other.name;
    	this.description = other.description;
    	this.modality = other.modality;
    	this.active = other.active;
    	this.changedBy = other.changedBy;
    	this.modality = other.modality;

    	this.exercises.addAll(other.exercises);
    	
    }
    
	
	public void upExercise(Exercise exec){
		int oldPos =  this.exercises.indexOf(exec);
		int newPos = oldPos - 1;
		
		if(oldPos == 0){
			return;
		}else{
			Collections.swap(exercises,oldPos, newPos);
		}
	}
	
	public void downExercise(Exercise exec){
		int oldPos =  this.exercises.indexOf(exec);
		int newPos = oldPos + 1;
		
		if(oldPos == this.exercises.size() - 1){
			return;
		}else{
			Collections.swap(exercises,oldPos, newPos);
		}
	}

	
	public void fillReferences(){
		if(!this.modality.getReferencedExerciseGroups().contains(this)){
			this.modality.getReferencedExerciseGroups().add(this);
		}
		for(Exercise exercise:this.exercises){
			if(!exercise.getReferencedExerciseGroups().contains(this)){
				exercise.getReferencedExerciseGroups().add(this);
			}	
		}
	
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getObs() {
		return obs;
	}

	public void setObs(String obs) {
		this.obs = obs;
	}

	public Date getCreatedAt() {
		return createdAt;
	}

	public void setCreatedAt(Date createdAt) {
		this.createdAt = createdAt;
	}

	public Date getLastChange() {
		return lastChange;
	}

	public void setLastChange(Date lastChange) {
		this.lastChange = lastChange;
	}

	public User getChangedBy() {
		return changedBy;
	}

	public void setChangedBy(User changedBy) {
		this.changedBy = changedBy;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	
	public Modality getModality() {
		return modality;
	}

	public void setModality(Modality modality) {
		this.modality = modality;
	}

	public List<Exercise> getExercises() {
		return exercises;
	}

	public void setExercises(List<Exercise> exercises) {
		this.exercises = exercises;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}
	
	public TrainingType getTrainingType() {
		return trainingType;
	}

	public void setTrainingType(TrainingType trainingType) {
		this.trainingType = trainingType;
	}

	public String getNameKey() {
		return nameKey;
	}


	public int getVersion() {
		return version;
	}

	public void setVersion(int version) {
		this.version = version;
	}

	public VersionableExerciseGroup getVersionableExerciseGroup() {
		return versionableExerciseGroup;
	}

	public void setVersionableExerciseGroup(
			VersionableExerciseGroup versionableExerciseGroup) {
		this.versionableExerciseGroup = versionableExerciseGroup;
	}
	

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = super.hashCode();
		result = prime * result + (active ? 1231 : 1237);
		result = prime * result
				+ ((changedBy == null) ? 0 : changedBy.hashCode());
		result = prime * result
				+ ((createdAt == null) ? 0 : createdAt.hashCode());
		result = prime * result
				+ ((description == null) ? 0 : description.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result
				+ ((lastChange == null) ? 0 : lastChange.hashCode());
		result = prime * result
				+ ((modality == null) ? 0 : modality.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((obs == null) ? 0 : obs.hashCode());
		result = prime * result
				+ ((trainingType == null) ? 0 : trainingType.hashCode());
		result = prime
				* result
				+ ((versionableExerciseGroup == null) ? 0
						: versionableExerciseGroup.hashCode());
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (!super.equals(obj)) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		ExerciseGroup other = (ExerciseGroup) obj;
		if (active != other.active) {
			return false;
		}
		if (changedBy == null) {
			if (other.changedBy != null) {
				return false;
			}
		} else if (!changedBy.equals(other.changedBy)) {
			return false;
		}
		if (createdAt == null) {
			if (other.createdAt != null) {
				return false;
			}
		} else if (!createdAt.equals(other.createdAt)) {
			return false;
		}
		if (description == null) {
			if (other.description != null) {
				return false;
			}
		} else if (!description.equals(other.description)) {
			return false;
		}
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (lastChange == null) {
			if (other.lastChange != null) {
				return false;
			}
		} else if (!lastChange.equals(other.lastChange)) {
			return false;
		}
		if (modality == null) {
			if (other.modality != null) {
				return false;
			}
		} else if (!modality.equals(other.modality)) {
			return false;
		}
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		if (obs == null) {
			if (other.obs != null) {
				return false;
			}
		} else if (!obs.equals(other.obs)) {
			return false;
		}
		if (trainingType == null) {
			if (other.trainingType != null) {
				return false;
			}
		} else if (!trainingType.equals(other.trainingType)) {
			return false;
		}
		if (versionableExerciseGroup == null) {
			if (other.versionableExerciseGroup != null) {
				return false;
			}
		} else if (!versionableExerciseGroup
				.equals(other.versionableExerciseGroup)) {
			return false;
		}
		return true;
	}


	@Override
	public String toString() {
		return "ExerciseGroup [id=" + id + ", name=" + name + ", description="
				+ description + ", obs=" + obs + ", createdAt=" + createdAt
				+ ", lastChange=" + lastChange + ", changedBy=" + changedBy
				+ ", active=" + active + ", trainingType=" + trainingType
				+ ", modality=" + modality + ", versionableExerciseGroup="
				+ versionableExerciseGroup + "]";
	}

	
	 
}
 
